//!引用&借用（References&Borrowing）
//规则:
// 1.同一时刻，最多只有一个可变借用（&mut T），或者2。
// 2.同一时刻，可有0个或多个不可变借用（&T）但不能有任何可变借用。
// 3.借用在离开作用域后释放。
// 4.在可变借用释放前不可访问源变量。

//总结
// 1.借用不改变内存的所有者（Owner），借用只是对源内存的临时引用。
// 2.在借用周期内，借用方可以读写这块内存，所有者被禁止读写内存；且所有者保证在有“借用”存在的情况下，不会释放或转移内存。
// 3.失去所有权的变量不可以被借用（访问）。
// 4.在租借期内，内存所有者保证不会释放/转移/可变租借这块内存，但如果是在非可变租借的情况下，所有者是允许继续非可变租借出去的。
// 5.借用周期满后，所有者收回读写权限
// 6.借用周期小于被借用者（所有者）的生命周期。


//通过&符号完成Borrowing：
#[test]
pub fn demo1(){
    //Borrowing(&x)并不会发生所有权moved，所以println可以同时访问x和y。 通过引用，就可以对普通类型完成修改。
    let x: Vec<i32> = vec!(1i32, 2, 3);
    let y = &x;
    println!("x={:?}, y={:?}", x, y);
}

//通过引用，就可以对普通类型完成修改。
#[test]
pub fn demo2(){
    let mut x: i32 = 100;
    {
        let y: &mut i32 = &mut x;
        *y += 2;
    }
    println!("{}", x); //102
}
//借用与引用的区别:借用与引用是一种相辅相成的关系，若B是对A的引用，也可称之为B借用了A。
//Rust用引用时，一定要注意应该在何处何时正确的“归回”借用/引用


//可变性,Borrowing也分“不可变借用”（默认，&T）和“可变借用”（&mut T）。
//顾名思义，“不可变借用”是只读的，不可更新被引用的内容。

#[test]
pub fn demo3(){
    let x: Vec<i32> = vec!(1i32, 2, 3);

    //可同时有多个不可变借用
    let y = &x;
    let z = &x;
    let m = &x;

    //ok
    println!("{:?}, {:?}, {:?}, {:?}", x, y, z, m);
}

//同一时刻只能有一个可变借用(&mut T)，且被借用的变量本身必须有可变性 :
#[test]
pub fn demo4(){
    //源变量x可变性
    let mut x: Vec<i32> = vec!(1i32, 2, 3);

    //只能有一个可变借用
    let y = &mut x;
    // let z = &mut x; //错误
    y.push(100);

    //ok
    println!("{:?}", y);

    //错误，可变借用未释放，源变量不可访问
    // println!("{:?}", x);
}  //y在此处销毁



//高级例子
#[test]
pub fn demo5(){
    let mut x: Vec<i32> = vec!(1_i32, 2, 3);
    //更新数组
    //push中对数组进行了可变借用，并在push函数退出时销毁这个借用
    x.push(10);

    {
        //可变借用1
        let mut y = &mut x;
        y.push(100);
        

        //可变借用2，注意：此处是对y的借用，不可再对x进行借用，
        //因为y在此时依然存活。
        let z = &mut y;
        z.push(1000);

        println!("{:?}", z); //打印: [1, 2, 3, 10, 100, 1000]
    } //y和z在此处被销毁，并释放借用。

    //访问x正常
    println!("{:?}", x); //打印: [1, 2, 3, 10, 100, 1000]
}

